package org.queryexecutor.database;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.Vector;

import javax.swing.table.AbstractTableModel;

import org.queryexecutor.main.Main;
import org.queryexecutor.swing.frames.MainFrame;

public class QueryTableModel extends AbstractTableModel
{
	
	private Vector<String[]>	cache;
	private int					colCount;
	private Statement			statement;
	private String[]			headers;
	private Connection			db;
	
	public QueryTableModel()
	{
		this.cache = new Vector<String[]>();
		this.colCount = 0;
	}
	
	/**
	 * 
	 */
	private static final long	serialVersionUID	= 1L;
	
	@Override
	public int getRowCount()
	{
		return this.cache.size();
	}
	
	@Override
	public int getColumnCount()
	{
		return this.colCount;
	}
	
	public void setQuery(String q)
	{
		this.cache = new Vector<String[]>();
		try {
			// Execute the query and store the result set and its metadata
			ResultSet rs = this.statement.executeQuery(q);
			ResultSetMetaData meta = rs.getMetaData();
			this.colCount = meta.getColumnCount();
			
			// Now we must rebuild the headers array with the new column names
			this.headers = new String[this.colCount];
			for(int h = 1; h <= this.colCount; h++) {
				this.headers[h - 1] = meta.getColumnName(h).toUpperCase();
			}
			
			// and file the cache with the records from our query. This would
			// not be
			// practical if we were expecting a few million records in response
			// to our
			// query, but we aren't, so we can do this.
			int ctr = 0;
			while(rs.next()) {
				String[] record = new String[this.colCount];
				for(int i = 0; i < this.colCount; i++) {
					record[i] = rs.getString(i + 1);
				}
				this.cache.addElement(record);
				ctr++;
				if(ctr == 1000) {
					Main.showMessage(MainFrame.getInstance(), "Query is limited to 1000 rows.",
							false);
					break;
				}
			}
			fireTableChanged(null); // notify everyone that we have a new table.
		} catch(Exception e) {
			this.cache.clear();
			Main.showException(e, MainFrame.getInstance());
		}
	}
	
	public String getColumnName(int i)
	{
		return this.headers[i];
	}
	
	public void initDB()
	{
		try {
			if(this.db != null) {
				if(this.statement != null) {
					return;
				}
			} else {
				this.db = DatabaseConnection.getInstance().getConnection();
			}
			this.statement = this.db.createStatement();
		} catch(Exception e) {
			System.out.println("Could not initialize the database.");
			e.printStackTrace();
		}
	}
	
	@Override
	public Object getValueAt(int row, int col)
	{
		return this.cache.elementAt(row)[col];
	}
	
}
